package com.hangwei.aicabinet.manager;

import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;

import com.hangwei.aicabinet.App;
import com.hangwei.aicabinet.util.ByteUtil;
import com.hangwei.aicabinet.util.Constant;
import com.hangwei.aicabinet.util.InstructionsUtil;
import com.hangwei.aicabinet.util.SPKey;
import com.hangwei.aicabinet.util.SPUtil;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;

import android_serialport_api.SerialPort;
import android_serialport_api.SerialPortFinder;

/**
 * author: 张龙臣
 * date: 2018-09-07.
 */

public class LoopManager {
    private static final int baudrate = 115200;//波特率（可自行设定）

    private static ArrayList<SerialPort> mSerialPorts;
    private static Thread mReceiveThread;
    private static Thread mSendThread;
    private static String order = "";

    private static ArrayList<String> mOrders;

    /**
     * 强制结束线程任务标识
     */
    private static boolean stopThread = false;
    private static InputStream mInputStream;
    private static OutputStream mOutputStream;
    private static SerialPort mSerialPort;
    public static HashMap<String, String> allTabFromRead;

    private static boolean getCard = false;

    @SuppressLint("HandlerLeak")
    private static Handler mReceiveHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 1) {
                String text = (String) msg.obj;
                if (getCard) {//从缓存中读取到的标签
//                    Log.d("allTabFromRead-text", text);
                    if (!InstructionsUtil.checkTabFromResponse(text)) {
                        Log.e("mReceiveHandler", "不是标签数据" + text);
                        getCard = false;
                        return;
                    }
                    HashMap<String, String> tabs = InstructionsUtil.getTabFromResponse(text);
                    if (tabs != null && tabs.size() > 0) {
                        allTabFromRead.putAll(tabs);
                        Set<String> keySet = allTabFromRead.keySet();
                        Log.d("keySet", keySet.toString());
                        Log.i("keySet", keySet.size() + "");
                        App.getmHandler().postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                order = Constant.From_Cache;  //接着读
                            }
                        }, 500);
                    }
                }
            }
        }
    };


    public static void loop() {
        if (allTabFromRead == null)
            allTabFromRead = new HashMap<>();
        else allTabFromRead.clear();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
//                    order = Constant.Read_Card;
//                    Log.d("Read_Card", Constant.Read_Card);
//                    Thread.sleep(1000);
                    order = Constant.Read_Card;
                    Log.d("Read_Card", Constant.Read_Card);
                    Thread.sleep(1500);
                    getCard = true;
                    Log.d("getCard", Constant.From_Cache);
                    Thread.sleep(500);
                    order = Constant.From_Cache;
                    Log.d("From_Cache", Constant.From_Cache);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

    public static void init() {
        mSerialPorts = new ArrayList<>();
        mOrders = new ArrayList<>();
        mOrders.add(Constant.Check_Available);
        mOrders.add(Constant.Set_Power);
        mOrders.add(Constant.Get_Antenna);
        mOrders.add(Constant.Set_Antenna);
    }

    public static void getAllDevices() {
        SerialPortFinder serialPortFinder = new SerialPortFinder();
        String[] allDevicesPath = serialPortFinder.getAllDevicesPath();
        if (allDevicesPath.length == 0) {
            Log.e("test", "串口初始化失败");
            Toast.makeText(App.getInstance(), "串口初始化失败", Toast.LENGTH_SHORT).show();
            return;
        }
        Log.d("test", "串口数量    " + allDevicesPath.length);
        SPUtil.setString(SPKey.Available_Path, "");
        openDevices(allDevicesPath);
        looperLocalPath();
//        String string = SPUtil.getString(SPKey.Available_Path, "");
//        if (TextUtils.isEmpty(string)) {
//            openDevices(allDevicesPath);
//            looperLocalPath();
//        } else openAvailableSerialPort(string);
    }

    private static void openAvailableSerialPort(String string) {
        Log.i("可用串口", string);
        try {
            mSerialPort = new SerialPort(new File(string), baudrate, 0);
            mInputStream = mSerialPort.getInputStream();
            mOutputStream = mSerialPort.getOutputStream();
            openReceiveThread();
            openSendThread();
            Initialization();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void Initialization() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    for (int i = 0; i < mOrders.size(); i++) {
                        order = mOrders.get(i);
                        Thread.sleep(400);
                    }
                    Thread.sleep(200);
                    App.getmHandler().post(new Runnable() {
                        @Override
                        public void run() {
                            loop();
                        }
                    });
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

//    private void checkAvailable(final long startTime) {
//        mHandler.postDelayed(new Runnable() {
//            @Override
//            public void run() {
//                String string = SPUtil.getString(SPKey.Receive, "");
//                if (TextUtils.isEmpty(string)) {
//                    long checkTime = System.currentTimeMillis();
//                    if (checkTime - startTime < 1000) {
//                        order = Constant.Check_Available;
//                        checkAvailable(startTime);
//                    }else {
//                        SPUtil.commitString(SPKey.Available_Path,"");
//                        Toast.makeText(SplashActivity.this,"串口不可用，重新打开APP试试~",Toast.LENGTH_SHORT).show();
//                    }
//                }
//            }
//        }, 100);
//    }

    /**
     * 执行找可用串口的同时，轮询查看是否已找到
     */
    private static void looperLocalPath() {
        App.getmHandler().postDelayed(new Runnable() {
            @Override
            public void run() {
                String string = SPUtil.getString(SPKey.Available_Path, "");
                if (TextUtils.isEmpty(string)) {
                    looperLocalPath();
                } else {
                    stopThread = true;
                    openAvailableSerialPort(string);
                }
            }
        }, 100);
    }


    /**
     * 找到那个可用的串口
     */
    private static void openDevices(String[] allDevicesPath) {
        //子线程开启前
        stopThread = false;
        try {
            for (final String path : allDevicesPath) {
                SerialPort serialPort = new SerialPort(new File(path), baudrate, 0);
                final InputStream inputStream = serialPort.getInputStream();
                final OutputStream outputStream = serialPort.getOutputStream();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            while (true) {
                                String string = SPUtil.getString(SPKey.Available_Path, "");
                                if (!TextUtils.isEmpty(string))
                                    break;
                                if (stopThread)
                                    break;
                                int available = inputStream.available();
                                if (available > 0) {
                                    byte[] buffer = new byte[available];
                                    int read = inputStream.read(buffer);
                                    String hexStr = ByteUtil.bytes2HexStr(buffer);
                                    Log.i("hexStr", path + "---" + hexStr);
                                    if (!TextUtils.isEmpty(hexStr) && hexStr.length() >= 10) {
                                        String substring = hexStr.substring(6, 10);
                                        if ("0000".equals(substring)) {
                                            //读写器在线
                                            SPUtil.setString(SPKey.Available_Path, path);
                                            Log.d("找到可用串口", path);
                                            closeUselessSerialPort();
                                        }
                                    }
                                    Thread.sleep(200);
                                } else {
                                    Thread.sleep(200);
                                    Log.i("path", path + "---" + stopThread);
                                }
                            }
                        } catch (IOException | InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        int n = 0;
                        try {
                            while (true) {
                                n++;
                                String string = SPUtil.getString(SPKey.Available_Path, "");
                                if (!TextUtils.isEmpty(string))
                                    break;
                                if (stopThread)
                                    break;
                                //读写器在线检测指令
                                byte[] bytes = ByteUtil.hexStr2bytes(Constant.Check_Available);
                                outputStream.write(bytes);
                                Log.i("outputStream", "---" + Constant.Check_Available + "--" + n);
                                Thread.sleep(200);
                            }
                        } catch (IOException | InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
            Log.e("openDevices", "打开串口失败");
        } finally {
            App.getmHandler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    Log.i("hexStr", "--111finally-" + stopThread);
                    closeUselessSerialPort();
                    String string = SPUtil.getString(SPKey.Available_Path, "");
                    if (TextUtils.isEmpty(string)) {
                        //强制结束线程任务
                        stopThread = true;
                        Log.i("hexStr", "--finally-" + stopThread);
                        //读写器在线检测 5 秒钟没有成功的响应
                        Toast.makeText(App.getInstance(), "无可用串口", Toast.LENGTH_SHORT).show();
                    }
                }
            }, 2000);
        }
    }

    int i = 0;

    private static void openReceiveThread() {
        mReceiveThread = new Thread() {
            @Override
            public void run() {
                try {
                    while (true) {
                        if (mInputStream == null) {
                            Log.e("openReceiveThread", "mInputStream == null");
                            break;
                        }

//                            Log.d("执行次数", "-----" + i);
                        int available = mInputStream.available();
                        if (available > 0) {
                            byte[] buffer = new byte[available];
                            int read = mInputStream.read(buffer);
                            String hexStr = ByteUtil.bytes2HexStr(buffer);
//                            SPUtil.commitString(SPKey.Receive, hexStr);
                            Message obtain = Message.obtain();
                            obtain.what = 1;
                            obtain.obj = hexStr;
                            Log.i("ReceiveThread", hexStr);
                            mReceiveHandler.sendMessage(obtain);
                            Thread.sleep(200);
                        } else {
                            Thread.sleep(200);
//                            Log.d("ReceiveThread无数据", "-----" + i);
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.e("IOException", "-----ReceiveThread------");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        mReceiveThread.start();
    }

    private static void openSendThread() {
        mSendThread = new Thread() {
            @Override
            public void run() {
                try {
                    while (true) {
                        if (mOutputStream == null) {
                            Log.e("openSendThread", "mOutputStream == null");
                            break;
                        }
                        if (TextUtils.isEmpty(order)) {
                            Thread.sleep(200);
                            continue;
                        }
                        byte[] bytes = ByteUtil.hexStr2bytes(order);
                        mOutputStream.write(bytes);
//                            SystemClock.sleep(200);
                        Log.i("SendThread", "发送成功:" + order);
                        order = "";
                    }
                } catch (IOException e) {
                    Log.e("IOException", "-----SendThread------");
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        };
        mSendThread.start();
    }

    private static void closeUselessSerialPort() {
        if (mSerialPorts != null) {
            for (SerialPort serialPort : mSerialPorts) {
                if (serialPort != null) {
                    InputStream inputStream = serialPort.getInputStream();
                    OutputStream outputStream = serialPort.getOutputStream();
                    serialPort.close();
                    if (inputStream != null)
                        try {
                            inputStream.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    if (outputStream != null)
                        try {
                            outputStream.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                }
            }
            mSerialPorts.clear();
        }
        mSerialPorts = null;
    }

    public static void closeSerialPort() {
        if (mSerialPort != null) {
            mSerialPort.close();
        }
        if (mInputStream != null) {
            try {
                mInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (mOutputStream != null) {
            try {
                mOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
